package com.hnfnu.controller;

import cn.hutool.extra.qrcode.QrCodeUtil;
import com.alibaba.fastjson.JSONObject;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.payment.facetoface.models.AlipayTradePrecreateResponse;
import com.hnfnu.constant.DonationsTradeNo;
import com.hnfnu.protocol.dto.*;
import com.hnfnu.entity.Donations;
import com.hnfnu.protocol.model.bo.DonationRecordAddRecordInputBO;
import com.hnfnu.protocol.model.bo.DonationRecordGetRecordsByProjectIdInputBO;
import com.hnfnu.protocol.vo.*;
//import com.hnfnu.service.DonationRecordService;
import com.hnfnu.utils.QRCodeUtil;
import com.hnfnu.utils.SnowflakeUtils;
import okhttp3.Response;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.*;

import java.math.BigInteger;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * 捐款
 */
@RestController
@RequestMapping("donations")
public class DonationsController extends BaseController{

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

//    @Autowired
//    private DonationRecordService donationRecordService;

    /**
     * 捐款单
     */
    @PostMapping("/makeDonation")
    public ResponseResult makeDonation(@RequestBody Donations donations) throws Exception {
        if (loginUser == null) {
            return new ResponseResult(500,"请登录", 2);
        }

        if(donations.getAmount() <= 0) {
            return new ResponseResult(500,"输入正确的金额");
        }

        donations.setUserId(loginUser.getId());
        donations.setUsername(loginUser.getName());
        //交易订单号
        donations.setTradeNo(SnowflakeUtils.getSnowId());
        DonationsTradeNo.setTradeNo(donations.getTradeNo());
        DonationsTradeNo.setUserId(loginUser.getId());
        // 待支付支付
        donations.setStatus("0");
        donations.setCreateTime(new Date());
        boolean flag = donationsService.save(donations);
        if (!flag) {
            return new ResponseResult(500,"系统异常！请稍后再试");
        }
        ValueOperations<String, Object> ops = redisTemplate.opsForValue();
        Double amount = (Double) ops.get("donationsTotalAmount");
        Double addAmount = donations.getAmount();
        double newAmount = 0;
        if (amount != null) {
            newAmount = addAmount + amount;
        }
        ops.set("donationsTotalAmount", newAmount);
        redisTemplate.delete("donationsPage");
        redisTemplate.delete("donationsIntervalNumber");
        redisTemplate.delete("donationsProvinceNumber");
        redisTemplate.delete("donationsMonthTrend");
        redisTemplate.delete("getProjectAmounts");
        redisTemplate.delete("donationsPurposeTotalAmount");
        redisTemplate.delete("donationsPurposeDetailPercent");

        Factory.setOptions(config);
        AlipayTradePrecreateResponse precreateResponse = Factory.Payment.FaceToFace().preCreate("慈善捐款", donations.getTradeNo(), donations.getAmount().toString());
        String httpBody = precreateResponse.getHttpBody();
        JSONObject jsonObject = JSONObject.parseObject(httpBody);
        String qrUrl = jsonObject.getJSONObject("alipay_trade_precreate_response").get("qr_code").toString();
        String qrImgUrl = QRCodeUtil.generateQRCodeBase64(qrUrl);
        DonationsPayVO payVO = new DonationsPayVO(qrImgUrl, donations.getTradeNo());
        return new ResponseResult(200,"捐款成功",payVO);
    }

    /**
     * 从区块链查
     * 根据项目 id 查询捐款单
     */
//    @GetMapping("/getDonationsByProjectId")
//    public ResponseResult getDonationsByProjectId(@Param("projectId") Integer projectId) {
//        DonationRecordGetRecordsByProjectIdInputBO inputBO = new DonationRecordGetRecordsByProjectIdInputBO();
//        inputBO.setProjectId(BigInteger.valueOf(projectId));
//        List<DonationsByProjectIdVO> donationsByProjectIdVOS = new ArrayList<>();
//        try {
//            List<Object> donationsObject = (List<Object>) donationRecordService.getRecordsByProjectId(inputBO).getReturnObject().get(0);
//            List<DonationsRecordDTO>  donationsRecordDTOS = new ArrayList<>();
//            donationsObject.forEach(o -> {
//                String donationString = o.toString();
//                String[] parts = donationString.substring(1, donationString.length() - 1).split(", ");
//                // 提取各个字段的值并转换为适当的数据类型
//                int id = Integer.parseInt(parts[0]);
//                int userId = Integer.parseInt(parts[1]);
//                int newProjectId = Integer.parseInt(parts[2]);
//                String message = parts[3];
//                double amount = Double.parseDouble(parts[4]);
//                SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//                Date timestamp;
//                try {
//                    timestamp = timeFormat.parse(parts[5]);
//                } catch (ParseException e) {
//                    throw new RuntimeException(e);
//                }
//                DonationsRecordDTO donationsRecordDTO = new DonationsRecordDTO(id, userId, newProjectId, message, amount, timestamp);
//                donationsRecordDTOS.add(donationsRecordDTO);
//            });
//
//            // 按最近的时间排序
//            donationsRecordDTOS.sort((d1, d2) -> d2.getDonationsTime().compareTo(d1.getDonationsTime()));
//            donationsRecordDTOS.forEach(o -> {
//                String username = donationsService.getUserNameByUserId(o.getUserId());
//                DonationsByProjectIdVO donationsByProjectIdVO = new DonationsByProjectIdVO(username, o.getAmount(), o.getDonationsTime(), o.getMessage());
//
//                donationsByProjectIdVOS.add(donationsByProjectIdVO);
//            });
//        } catch (Exception e) {
//            return new ResponseResult(500, "查询失败");
//        }
//        return new ResponseResult(200, "区块链捐款信息", donationsByProjectIdVOS);
//    }

    /**
     * 获取捐款单
     */
    @GetMapping("/getDonationsPage")
    public ResponseResult getDonationsPage(){

        ValueOperations<String, Object> ops = redisTemplate.opsForValue();
        List<DonationsPageDTO> page = (List<DonationsPageDTO>) ops.get("donationsPage");
        if (page != null) {
            return new ResponseResult(200, "分页捐款单", page);
        }
        List<DonationsPageDTO> donationsPage = donationsService.getDonationsPage();
        ops.set("donationsPage",donationsPage);
        return new ResponseResult(200, "分页捐款单", donationsPage);
    }

    /**
     * 投票满意度
     */
    @PostMapping("/addSatisfaction")
    public ResponseResult addSatisfaction(@Param("grade") Integer grade) {
        boolean flag = donationsService.addSatisfaction(grade);
        if (!flag) {
            return new ResponseResult(500,"系统异常！请稍后再试");
        }
        redisTemplate.delete("donationsSatisfaction");
        return new ResponseResult(500,"投票成功");
    }

    /**
     * 可视化大屏所有数据
     */
    @GetMapping("/getAll")
    public  ResponseResult getAll() {
        ValueOperations<String, Object> ops = redisTemplate.opsForValue();
        List<DonationsIntervalDTO> intervalNumberRedis = (List<DonationsIntervalDTO>) ops.get("donationsIntervalNumber");
        List<DonationsProvinceDTO> provinceNumberReids = (List<DonationsProvinceDTO>) ops.get("donationsProvinceNumber");
        List<DonationsMonthTrendDTO> monthTrendRedis = (List<DonationsMonthTrendDTO>) ops.get("donationsMonthTrend");
        List<DonationsProjectNameAmountsDTO> projectAmountsRedis = (List<DonationsProjectNameAmountsDTO>) ops.get("getProjectAmounts");
        Double amountRedis = (Double) ops.get("donationsTotalAmount");
        List<DonationsSatisfactionDTO> satisfactionReids = (List<DonationsSatisfactionDTO>) ops.get("donationsSatisfaction");
        List<DonationsPurposeDTO> purposeTotalAmountRedis = (List<DonationsPurposeDTO>) ops.get("donationsPurposeTotalAmount");
        List<DonationsPurposeDetailPercentDTO> purposeDetailPercentRedis = (List<DonationsPurposeDetailPercentDTO>) ops.get("donationsPurposeDetailPercent");

        if (intervalNumberRedis == null) {
            intervalNumberRedis = donationsService.getIntervalNUmber();
            ops.set("donationsIntervalNumber", intervalNumberRedis);
        }

        if (provinceNumberReids == null) {
            provinceNumberReids = donationsService.getProvinceNumber();
            ops.set("donationsProvinceNumber", provinceNumberReids);
        }

        if (monthTrendRedis == null) {
            monthTrendRedis = donationsService.getMonthTrend();
            ops.set("donationsMonthTrend", monthTrendRedis);
        }

        if (projectAmountsRedis == null) {
            projectAmountsRedis = donationsService.getProjectAmounts();
            ops.set("getProjectAmounts", projectAmountsRedis);
        }

        if (amountRedis == null) {
            amountRedis = donationsService.getTotalAmount();
            ops.set("donationsTotalAmount",amountRedis);
        }

        if (satisfactionReids == null) {
            satisfactionReids = donationsService.getSatisfaction();
            ops.set("donationsSatisfaction", satisfactionReids);
        }

        if (purposeTotalAmountRedis == null) {
            purposeTotalAmountRedis = donationsService.getPurposeTotalAmount();
            ops.set("donationsPurposeTotalAmount",purposeTotalAmountRedis);
        }

        if (purposeDetailPercentRedis == null) {
            purposeDetailPercentRedis = donationsService.getPurposeDetailPercent();
            ops.set("donationsPurposeDetailPercent", purposeDetailPercentRedis);
        }

        DonationsAllVO donationsAllVO = new DonationsAllVO(
                intervalNumberRedis,
                provinceNumberReids,
                monthTrendRedis,
                projectAmountsRedis,
                amountRedis,
                satisfactionReids,
                purposeTotalAmountRedis,
                purposeDetailPercentRedis );

        return new ResponseResult(200, "All Donations Data", donationsAllVO);

    }

    /**
     *  今日捐款人数， 总捐款人数
     */

    @GetMapping("/getNumberOfDonors")
    public ResponseResult getNumberOfDonors(@Param("projectId") Integer projectId) {
        NumberOfDonorsVO numberOfDonors = donationsService.getNumberOfDonors(projectId);
        return new ResponseResult(200, "今日捐款人数， 总捐款人数", numberOfDonors);
    }

    /**
     * 各省份捐款的人数
     */

    @GetMapping("/getProvinceNumber")
    public ResponseResult getProvinceNumber() {
        return new ResponseResult(200, "各省份捐款的人数", donationsService.getProvinceNumber());
    }
    /**
     * 用户满意度评分
     */
    @GetMapping("/getSatisfaction")
    public ResponseResult getSatisfaction() {
        List<DonationsSatisfactionDTO> donationsSatisfactionDTO = donationsService.getSatisfaction();
        return new ResponseResult(200, "用户满意度评分", donationsSatisfactionDTO);
    }

    /**
     * 男女比例查询
     */
    @GetMapping("/getGenderRatio")
    public ResponseResult getGenderRatio() {
        // 男性的个数
        int maleNumber = donationsService.getMaleNumber();
        // 女性的个数
        int femaleNumber = donationsService.getFemaleNumber();
        HashMap<String,Integer> map = new HashMap<>();
        map.put("maleNumber",(int)Math.round((maleNumber) * 1.0 / (maleNumber + femaleNumber) * 100));
        map.put("femaleNumber",(int)Math.round((femaleNumber) * 1.0 / (maleNumber + femaleNumber) * 100));
        return new ResponseResult(200, "男女比例查询", map);
    }

    /**
     * 每月趋势查询
     */
    @GetMapping("/getMonthTrend")
    public ResponseResult getMonthTrend() {
        return new ResponseResult(200, "每月趋势查询", donationsService.getMonthTrend());
    }

    /**
     * 年龄段人数查询
     */
    @GetMapping("/getAgeInterval")
    public ResponseResult getAgeInterval() {
        int firstAgeStep = donationsService.getAgeInvalNumber(0,20);
        int secondAgeStep = donationsService.getAgeInvalNumber(21,30);
        int thirdAgeStep = donationsService.getAgeInvalNumber(31,40);
        int fourthAgeStep = donationsService.getAgeInvalNumber(41,50);
        int fifthAgeStep = donationsService.getAgeInvalNumber(51,100);
        HashMap<String,Integer> map = new HashMap<>();
        int total = firstAgeStep + secondAgeStep + thirdAgeStep + fourthAgeStep + fifthAgeStep;
        map.put("firstAgeStep",(int)Math.round((firstAgeStep) * 1.0 / total * 100));
        map.put("secondAgeStep",(int)Math.round((secondAgeStep) * 1.0 / total * 100));
        map.put("thirdAgeStep",(int)Math.round((thirdAgeStep) * 1.0 / total * 100));
        map.put("fourthAgeStep",(int)Math.round((fourthAgeStep) * 1.0 / total * 100));
        map.put("fifthAgeStep",(int)Math.round((fifthAgeStep) * 1.0 / total * 100));
        return new ResponseResult(200, "年龄段人数查询", map);
    }

    /**
     * 用户总人数查询
     */
    @GetMapping("/getTotalNumberOfUsers")
    public ResponseResult getTotalNumberOfUsers() {
        int total = donationsService.getTotalNumberOfUsers();
        int male = donationsService.getMaleNumber();
        int female = donationsService.getFemaleNumber();
        HashMap<String,Integer> map = new HashMap<>();
        map.put("totalNum",total);
        map.put("maleNum",male);
        map.put("femaleNum",female);
        return new ResponseResult(200, "用户总人数查询",map);
    }

    /**
     * 项目各种阶段的数目
     */

    @GetMapping("/getProjectStage")
    public ResponseResult getProjectStage() {
        int start = donationsService.getProjectStageNumber("start");
        int end = donationsService.getProjectStageNumber("end");
        int middle = donationsService.getProjectStageNumber("middle");
        HashMap<String ,Integer> map = new HashMap<>();
        map.put("完成占比", (int)Math.round((end) * 1.0 / (start + middle + end) * 100));
        map.put("开始项目",start);
        map.put("进行中",middle);
        map.put("结束项目",end);
        return new ResponseResult(200, "项目各种阶段的数目",map);
    }

    /**
     * 已筹集资金，与目标
     */
    @GetMapping("/getGoalAndRaised")
    public ResponseResult getGoalAndRaised(@Param("projectId") Integer projectId) {
        Double raised = donationsService.getRaised(projectId);
        if (raised == null) {
            raised = 0.0d;
        }
        Double goal = projectService.getGoal(projectId);
        if (goal == null) {
            goal = 0.0d;
        }
        DonationsGoalAndRaisedVO goalAndRaisedVO = new DonationsGoalAndRaisedVO(raised, goal);
        return new ResponseResult(200,"已筹集资金，与目标", goalAndRaisedVO);
    }

    /**
     * 查询本周评论数，发帖数，新增项目数，新增用户数，新增捐款数
     */
    @GetMapping("/getMiscellany")
    public ResponseResult getMiscellany() {
        //获取本周评论数
        int commentNum = commentService.getWeekCommentNum();
        //获取本周用户发帖数
        int postNum = articleService.getWeekArticleNum();
        //获取本周新项目
        int newProjectNum = projectService.getWeekProjectNum();
        //获取本周新增用户数
        int newUserNum = userService.getWeekUserNum();
        //获取本周新增捐款数
        double newDonationNum = donationsService.getWeekDonationNum();
        HashMap<String,Object> map = new HashMap<>();
        map.put("commentNum",commentNum);
        map.put("postNum",postNum);
        map.put("newProjectNum",newProjectNum);
        map.put("newUserNum",newUserNum);
        map.put("newDonationNum",newDonationNum);
        return new ResponseResult(200, "查询本周评论数，发帖数，新增项目数，新增用户数，新增捐款数 查询成功~~~success",map);
    }

    /**
     * 查询三大类型分布比例
     */
    @GetMapping("/getPurposeDetailPercent")
    public ResponseResult getPurposeDetailPercent() {
        return new ResponseResult(200, "查询三大类型分布比例", donationsService.getPurposeDetailPercent());
    }

    @GetMapping("/isPay")
    public ResponseResult isPay(@Param("tradeNo") String tradeNo) {
        Donations donations = donationsService.getByTrade(tradeNo);
        if (donations == null) {
            return new ResponseResult(500,"无订单",(Object)"0");
        }
        String status = donations.getStatus();
        return new ResponseResult(200, "支付状态",(Object) status);
    }

    /**
     * 查询今年总获赠
     */
    @GetMapping("/getDonations")
    public ResponseResult getAllDonations(){
        return new ResponseResult(200,"查询今年总获赠",donationsService.getTotalAmount());
    }
}

